Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encode Node information in separate types in aggregation rules #137

Merged
merged 31 commits into from
Sep 11, 2020

Conversation

eapolinario
Copy link
Contributor

@eapolinario eapolinario commented Aug 28, 2020

This PR redefines how the node information is used in aggregation rules.

So far we have relied on the presence of the NodeFieldType to decide which field from the envoy Node object we used for both (1) matching, and (2) fragment generation. In this PR we define separate types for each one of the two cases (i.e. (1) and (2)).

As we spoke offline, we opted for not using the envoy protos, instead, we're going to maintain a mapping between the envoy objects and the objects needed to perform (1) and (2) so as to isolate ourselves from other migration issues. Concretely, the envoy v2/v3 Locality object has its properties duplicated in our copy of the LocalityMatch and LocalityResultAction.

The idea behind this refactoring is to allow for better extensibility of both the matching and fragment generation phases. In summary, the process of adding a new type of aggregation rule object consists of a 2 step process:

  1. Add a pair of types to do (1) and (2) to the aggregation rules proto.
  2. Handle the newly added types in the process the types added in the above step in the mapper (including unit tests).

A followup PR is going to follow the model proposed in this PR to add support for node metadata.

eapolinario added 27 commits August 28, 2020 11:28
Signed-off-by: eapolinario <[email protected]>
Signed-off-by: eapolinario <[email protected]>
Signed-off-by: eapolinario <[email protected]>
Signed-off-by: eapolinario <[email protected]>
Signed-off-by: eapolinario <[email protected]>
Signed-off-by: eapolinario <[email protected]>
Signed-off-by: eapolinario <[email protected]>
Signed-off-by: eapolinario <[email protected]>
Signed-off-by: eapolinario <[email protected]>
Signed-off-by: eapolinario <[email protected]>
Signed-off-by: eapolinario <[email protected]>
Signed-off-by: eapolinario <[email protected]>
Signed-off-by: eapolinario <[email protected]>
Signed-off-by: eapolinario <[email protected]>
Signed-off-by: eapolinario <[email protected]>
@eapolinario eapolinario changed the title WIP - Encode Node information in separate types in aggregation rules Encode Node information in separate types in aggregation rules Sep 1, 2020
samrabelachew
samrabelachew previously approved these changes Sep 11, 2020
Copy link
Contributor

@samrabelachew samrabelachew left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Copy link
Contributor

@jyotimahapatra jyotimahapatra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The structure makes the yaml much readable. I've some concerns about using the corev2 protos outside of transport package. Can we isolate the usage?

@@ -9,8 +9,7 @@ fragments:
- "type.googleapis.com/envoy.api.v2.RouteConfiguration"
result:
request_node_fragment:
field: 1
action:
cluster_action:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i like how its a named action, instead of field: 1

internal/app/mapper/mapper.go Outdated Show resolved Hide resolved
eapolinario added 2 commits September 11, 2020 14:01
default:
return false, fmt.Errorf("RequestNodeMatch does not have a valid NodeFieldType")

// By construction only one of these is set at any point in time, so checking one by one
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jyotimahapatra , do you know if there's a way to preserve the switch-like functionality here? From a correctness perspective my comment is true, albeit less performant than the old code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we don't have a way to deal with the oneof fields using switch.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably compareString(idMatch, req.GetNodeID()) || compareString(clusterMatch, req.GetCluster()) || compareLocality(localityMatch, req.GetLocality()) and deal with nilness inside compareString. But compareString returns 2 values 😞

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

relying on short-circuiting is not better in terms of perf than what I'm proposing here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think what we have here works.

Copy link
Contributor

@jyotimahapatra jyotimahapatra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm and few questions

default:
return false, fmt.Errorf("RequestNodeMatch does not have a valid NodeFieldType")

// By construction only one of these is set at any point in time, so checking one by one
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we don't have a way to deal with the oneof fields using switch.

default:
return false, fmt.Errorf("RequestNodeMatch does not have a valid NodeFieldType")

// By construction only one of these is set at any point in time, so checking one by one
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably compareString(idMatch, req.GetNodeID()) || compareString(clusterMatch, req.GetCluster()) || compareLocality(localityMatch, req.GetLocality()) and deal with nilness inside compareString. But compareString returns 2 values 😞

}

// N.B.: join matches using "|" to indicate they all came from the locality object.
return strings.Join(matches, "|"), nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not for this PR. We might want to document it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wondering if a mapper_test should cover this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the tests I added in mapper_test all rely on behavior, e.g.

fmt.Sprintf("%s|%s|%s", noderegion, nodezone, nodesubzone),
.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for showing this

@eapolinario eapolinario merged commit f875109 into envoyproxy:master Sep 11, 2020
},
},
{
Description: "RequestNodeMatch with regex match request node zone mismatch",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we removed this tests by mistake? Lets add them back

Copy link
Contributor

@jyotimahapatra jyotimahapatra Sep 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the list that needs adding back.

RequestNodeMatch with node region regex does not match
RequestNodeMatch with node zone regex does not match
RequestNodeMatch with node subzone regex does not match
RequestNodeMatch with regex match request node region mismatch
RequestNodeMatch with regex match request node zone mismatch
empty node region in request predicate
empty node zone in request predicate
empty node subzone in request predicate
non matching field type

@eapolinario eapolinario mentioned this pull request Sep 12, 2020
samrabelachew pushed a commit to samrabelachew/xds-relay that referenced this pull request Sep 21, 2020
…proxy#137)

* Add NodeStringMatch proto definitions

Signed-off-by: eapolinario <[email protected]>

* Expose Locality in RequestV2

Signed-off-by: eapolinario <[email protected]>

* Replace uses of node field type in isNodeMatch

Signed-off-by: eapolinario <[email protected]>

* fix mapper_test tests cases related to node cluster and node id.

Signed-off-by: eapolinario <[email protected]>

* lint

Signed-off-by: eapolinario <[email protected]>

* Use the new protos in tests

Signed-off-by: eapolinario <[email protected]>

* bump dependencies.

Signed-off-by: eapolinario <[email protected]>

* more tests.

Signed-off-by: eapolinario <[email protected]>

* Fix remaining unit tests.

Signed-off-by: eapolinario <[email protected]>

* remove TODO from proto

Signed-off-by: eapolinario <[email protected]>

* Remove getResultRequestNodeFragment

Signed-off-by: eapolinario <[email protected]>

* Fix yaml_proto tests

Signed-off-by: eapolinario <[email protected]>

* Add NodeLocality to RequestNodeFragment

Signed-off-by: eapolinario <[email protected]>

* Edit getResultFromRequestNodePredicate

Signed-off-by: eapolinario <[email protected]>

* fix integration tests

Signed-off-by: eapolinario <[email protected]>

* delete unused getNodeValue function

Signed-off-by: eapolinario <[email protected]>

* Fix e2e test.

Signed-off-by: eapolinario <[email protected]>

* uncomment Locality tests

Signed-off-by: eapolinario <[email protected]>

* Define LocalityResultAction

Signed-off-by: eapolinario <[email protected]>

* fix example aggregation rules file.

Signed-off-by: eapolinario <[email protected]>

* s/NodeStringMatch/StringMatch/g

Signed-off-by: eapolinario <[email protected]>

* s/NodeLocalityMatch/LocalityMatch + use StringMatch

Signed-off-by: eapolinario <[email protected]>

* lint

Signed-off-by: eapolinario <[email protected]>

* remove NodeFieldType enum.

Signed-off-by: eapolinario <[email protected]>

* more linting

Signed-off-by: eapolinario <[email protected]>

* remove mentions to enum in test file.

Signed-off-by: eapolinario <[email protected]>

* Remove mentions to corev2.Locality and use our own Locality object

Signed-off-by: eapolinario <[email protected]>

* remove TODO in mapper.

Signed-off-by: eapolinario <[email protected]>

* remove individual Locality properties.

Signed-off-by: eapolinario <[email protected]>
Signed-off-by: Samra Belachew <[email protected]>
jyotimahapatra pushed a commit that referenced this pull request Nov 19, 2020
This PR adds a matcher for node metadata fields. This is for #125.

Similarly to #137, we encode the node metadata information required in the aggregation rules in a pair of protos: (1) NodeMetadataMatch, and (2) NodeMetadataAction, the former related to the matching process, whereas the latter has to do with the formation of the fragment.

Envoy's node metadata is an opaque struct of type google.protobuf.Struct, which basically represents a dictionary of strings to Value.

This PR adds support for 3 of the 6 values: string, bool, and a nested struct of Value. The support for these other types is going to be added in separate PRs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants